﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using log4net;

namespace WINADM.Server.WMI
{
    public class Win32ServiceHelper : IWin32ServiceHelper
    {
        ILog _logger;
        public Win32ServiceHelper(ILog logger)
        {
            _logger = logger;
        }
        public IList<Win32Service> GetAllServices()
        {
            IList<Win32Service> win32Services = new List<Win32Service>();

            try
            {
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(WMIConstants.WMIRootNamespace, WMIConstants.WMIQuery_AllServiceQuery);

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    win32Services.Add(new Win32Service(queryObj));

                }
            }
            catch (Exception ex)
            {
                _logger.Error("Error occured while fetching service information", ex);
            }
            return win32Services;
        }

        public IList<Win32DependentService> GetAllDependentService()
        {
            IList<Win32DependentService> dependentService = new List<Win32DependentService>();
            try
            {
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(WMIConstants.WMIRootNamespace, WMIConstants.WMIQuery_AllDependentServiceQuery);

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    dependentService.Add(new Win32DependentService(queryObj));

                }
            }
            catch (Exception ex)
            {
                _logger.Error("Error occured while fetching dependent service information", ex);
            }
            return dependentService;
        }

        public bool StartService(string win32ServiceName)
        {
            try
            {
                ManagementObject classInstance =
                    new ManagementObject(WMIConstants.WMIRootNamespace, String.Format(WMIConstants.WMIQuery_SingleServiceQuery, win32ServiceName),
                    null);

                // Execute the method and obtain the return values.
                ManagementBaseObject outParams =
                    classInstance.InvokeMethod(WMIConstants.WMIMethod_Win32Service_StartService, null, null);


                int returnVal = Convert.ToInt32(outParams[WMIConstants.WMIMethodReturnValue]);

                if (returnVal == 0)
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                _logger.Error("An error occurred while trying to execute the start service WMI method: ", ex);
            }
            return false;
        }

        public bool StopService(string win32ServiceName)
        {
            return InvokeWMIMethod(win32ServiceName,WMIConstants.WMIMethod_Win32Service_StopService);
        }
        
        public bool PauseService(string win32ServiceName)
        {
            return InvokeWMIMethod(win32ServiceName, WMIConstants.WMIMethod_Win32Service_PauseService);
        }
        public bool ResumeService(string win32ServiceName)
        {
            return InvokeWMIMethod(win32ServiceName, WMIConstants.WMIMethod_Win32Service_ResumeService);
        }
        public bool DeleteService(string win32ServiceName)
        {
            return InvokeWMIMethod(win32ServiceName, WMIConstants.WMIMethod_Win32Service_DeleteService);
        }

        private bool InvokeWMIMethod(string win32ServiceName, string methodName)
        {
            try
            {
                ManagementObject classInstance =
                    new ManagementObject(WMIConstants.WMIRootNamespace, String.Format(WMIConstants.WMIQuery_SingleServiceQuery, win32ServiceName),
                    null);

                // Execute the method and obtain the return values.
                if(classInstance == null)
                    throw new WMIOperationException(String.Format(WMIConstants.WMIMethod_ServiceInstance_Null_Message, win32ServiceName));

                ManagementBaseObject outParams = classInstance.InvokeMethod(methodName, null, null);

                UInt32 returnVal = Convert.ToUInt32(outParams[WMIConstants.WMIMethodReturnValue]);

                if (returnVal == 0)
                    return true;
                else
                    throw new WMIOperationException(String.Format(WMIConstants.WMIMethod_InvokeMethod_UnSuccessfull_Message,methodName,
                        win32ServiceName,DecodeMethodReturnVal(returnVal)));
            }
            catch (Exception ex)
            {
                _logger.Error(String.Format(WMIConstants.WMIMethod_InvokeMethod_Exception_Message, methodName), ex);
                throw new WMIOperationException(String.Format(WMIConstants.WMIMethod_InvokeMethod_Exception_Message,
                    methodName) + "::" + ex.Message, ex);
            }
        }

        private string DecodeMethodReturnVal(UInt32 returval)
        {
            return String.Empty;
        }



    }


}
